package org.example;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 现约定软件版本号格式为三段x.y.z，x段表示主版本，y段表示次要版本，z段表示修订版本，
 * y段、z段是可选的(即可以为 x.y或 x)，每段的值范围是 [0,999]之间的整数。
 *
 * 软件的兼容、依赖等管理中，通常需要用到「版本范围」，一种「版本范围」的表示方法为 前缀x.y.z，说明如下:
 * 前缀为=、>、 >=、<、<=，分别表示等于、大于、大于等于、小于、小于等于给定版本。若未给定y段或z段，则表示y=0 或 z=0
 * 前缀为~，表示的版本范围如下:
 * 1.如果给定了次要版本，则从该版本到下一个次要版本(不包括下个次要版本)。若末给定z段，则表示z=0
 * 如 ~1.9 次要版本9的下一次要版本是10，表示范围为[1.9.0,1.10.0)即[1.9.0, 1.9.999]
 * 如~1.9.5 表示[1.9.5,1.10.0)即[1.9.5,1.9.999]
 * 如 ~1.0.0 表示[1.0.0,1.1.0)即 [1.0.0,1.0.999]
 * 2.如果末给定次要版本(即仅有主版本)，则从该版本到下一个主版
 * 本(不包括下一个主版本)。未给定的y段和z段均为0
 * 如-1表示[1.0.0,2.0.0)即[1.0.0,1.999.999];注意它与 ~1.0.0或~1.0 是不同的
 *
 * 现给出多对「版本范围」rangePairs;rangePairs[i]=[rangeA,range8]，
 * 如果存在交集(即存在版本同时满足两个范围)输出字符串 yes ，否则输出 no
 */
public class Solution {
//    List<String> checkVersionRange(List<List<String>> rangePairs){
//        return new ArrayList<>();
//    }

    public static void main(String[] args) {
        List<List<String>> rangePairs = Arrays.asList(
                Arrays.asList(">1.0.0", "<=1.0.0"),
                Arrays.asList("<1.2.0", ">1.1.999"),
                Arrays.asList("~0.10", "=0.10.0"),
                Arrays.asList("=99.0","~99")
        );
        Solution solution = new Solution();
        List<String> ans = solution.checkVersionRange(rangePairs);
        // ["no","no","yes","yes"]
        System.out.println(ans);
    }

    // 主方法
    public List<String> checkVersionRange(List<List<String>> rangePairs) {
        List<String> res = new ArrayList<>();
        for (List<String> pair : rangePairs) {
            VersionRange range1 = parseRange(pair.get(0));
            VersionRange range2 = parseRange(pair.get(1));
            if (hasIntersection(range1, range2)) {
                res.add("yes");
            } else {
                res.add("no");
            }
        }
        return res;
    }

    // 解析版本范围
    private VersionRange parseRange(String rangeStr) {
        String op;
        String version;
        if (rangeStr.startsWith(">=") || rangeStr.startsWith("<=")) {
            op = rangeStr.substring(0, 2);
            version = rangeStr.substring(2);
        } else if (rangeStr.startsWith(">") || rangeStr.startsWith("<") || rangeStr.startsWith("=") || rangeStr.startsWith("~")) {
            op = rangeStr.substring(0, 1);
            version = rangeStr.substring(1);
        } else {
            // 默认等于
            op = "=";
            version = rangeStr;
        }

        int[] ver = parseVersion(version);

        switch (op) {
            case "=":
                return new VersionRange(ver, ver);
            case ">":
                return new VersionRange(incVersion(ver), new int[]{999, 999, 999});
            case ">=":
                return new VersionRange(ver, new int[]{999, 999, 999});
            case "<":
                return new VersionRange(new int[]{0, 0, 0}, decVersion(ver));
            case "<=":
                return new VersionRange(new int[]{0, 0, 0}, ver);
            case "~":
                int[] start = ver;
                int[] end;
                if (ver[1] != 0 || rangeStr.contains(".")) {
                    // ~x.y or ~x.y.z -> 到下一y版本
                    end = new int[]{ver[0], ver[1] + 1, 0};
                    end = decVersion(end);
                } else {
                    // ~x -> 到下一主版本
                    end = new int[]{ver[0] + 1, 0, 0};
                    end = decVersion(end);
                }
                return new VersionRange(start, end);
            default:
                throw new IllegalArgumentException("Invalid range prefix: " + op);
        }
    }

    // 判断两个区间是否有交集
    private boolean hasIntersection(VersionRange a, VersionRange b) {
        return compareVersion(a.end, b.start) >= 0 && compareVersion(b.end, a.start) >= 0;
    }

    // 解析版本字符串 → int[3]
    private int[] parseVersion(String verStr) {
        String[] parts = verStr.split("\\.");
        int[] ver = new int[3];
        for (int i = 0; i < parts.length; i++) {
            ver[i] = Integer.parseInt(parts[i]);
        }
        return ver;
    }

    // 比较两个版本号（返回 -1、0、1）
    private int compareVersion(int[] a, int[] b) {
        for (int i = 0; i < 3; i++) {
            if (a[i] != b[i]) return a[i] - b[i];
        }
        return 0;
    }

    // 将版本+1（比如 >1.2.3，表示从1.2.4开始）
    private int[] incVersion(int[] ver) {
        int[] res = Arrays.copyOf(ver, 3);
        if (++res[2] > 999) {
            res[2] = 0;
            if (++res[1] > 999) {
                res[1] = 0;
                res[0]++;
            }
        }
        return res;
    }

    // 将版本-1（比如 <1.2.0，表示到1.1.999）
    private int[] decVersion(int[] ver) {
        int[] res = Arrays.copyOf(ver, 3);
        if (--res[2] < 0) {
            res[2] = 999;
            if (--res[1] < 0) {
                res[1] = 999;
                res[0]--;
            }
        }
        return res;
    }

    // 封装版本区间
    static class VersionRange {
        int[] start;
        int[] end;

        VersionRange(int[] start, int[] end) {
            this.start = start;
            this.end = end;
        }
    }
}
